// Licensed to Cloudera, Inc. under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  Cloudera, Inc. licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package com.cloudera.api.model;

import com.google.common.base.Objects;
import com.google.common.base.Preconditions;

import java.util.Date;
import java.util.Map;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.joda.time.Duration;


/**
 * Represents an Impala Query.
 */
@XmlRootElement(name = "impalaQuery")
public class ApiImpalaQuery {

  private String queryId;
  private String statement;
  private String queryType;
  private String queryState;
  private Date startTime;
  private Date endTime;
  private Long rowsProduced;
  private Map<String, String> attributes;
  private String user;
  private ApiHostRef coordinator;
  private boolean detailsAvailable;
  private String database;
  private Long durationMillis;

  public ApiImpalaQuery() {
    // For JAX-B
  }

  public ApiImpalaQuery(String queryId,
                        String statement,
                        String queryType,
                        String queryState,
                        Date startTime,
                        Date endTime,
                        Long rowsProduced,
                        Map<String, String> syntheticAttributes,
                        String user,
                        String frontEndHostId,
                        boolean runtimeProfileAvailable,
                        String defaultDatabase,
                        Duration duration) {
    Preconditions.checkNotNull(queryId);
    this.queryId = queryId;
    this.statement = statement;
    this.queryType = queryType;
    this.queryState = queryState;
    this.startTime = startTime;
    this.endTime = endTime;
    this.rowsProduced = rowsProduced;
    this.attributes = syntheticAttributes;
    this.user = user;
    coordinator = new ApiHostRef(frontEndHostId);
    this.detailsAvailable = runtimeProfileAvailable;
    this.database = defaultDatabase;
    durationMillis =  duration == null ? null : duration.getMillis();
  }

  /** The query id. */
  @XmlElement
  public String getQueryId() {
    return queryId;
  }
  
  public void setQueryId(String queryId) {
    this.queryId = queryId;
  }

  /** The SQL statement for the query. */
  @XmlElement
  public String getStatement() {
    return statement;
  }

  public void setStatement(String statement) {
    this.statement = statement;
  }
  
  /** 
   * The query type. The possible values are: DML, DDL, QUERY and UNKNOWN.
   * See the Impala documentation for more details.
   */
  @XmlElement
  public String getQueryType() {
    return queryType;
  }
  
  public void setQueryType(String queryType) {
    this.queryType = queryType;
  }

  /** 
   * The query state. The possible values are: CREATED, INITIALIZED, COMPILED,
   * RUNNING, FINISHED, EXCEPTION, and UNKNOWN.
   * See the Impala documentation for more details.
   */
  @XmlElement
  public String getQueryState() {
    return queryState;
  }
  
  public void setQueryState(String queryState) {
    this.queryState = queryState;
  }

  /** The time the query was issued. */
  @XmlElement
  public Date getStartTime() {
    return startTime;
  }
  
  public void setStartTime(Date startTime) {
    this.startTime = startTime;
  }

  /** 
   * The time the query finished. If the query hasn't finished then this
   * will return null.
   */
  @XmlElement
  public Date getEndTime() {
    return endTime;
  }
  
  public void setEndTime(Date endTime) {
    this.endTime = endTime;
  }

  /** 
   * The number of rows produced by the query. If the query hasn't completed
   * this will return null.
   */
  public Long getRowsProduced() {
    return rowsProduced;
  }
  
  public void setRowsProduced(Long rowsProduced) {
    this.rowsProduced = rowsProduced;
  }

  /**
   * A map of additional query attributes which is generated by Cloudera Manager.
   */
  public Map<String, String> getAttributes() {
    return attributes;
  }
  
  public void setAttributes(Map<String, String> attributes) {
    this.attributes = attributes;
  }

  /** The user who issued this query. */
  public String getUser() {
    return user;
  }
  
  public void setUser(String user) {
    this.user = user;
  }

  /** The host of the Impala Daemon coordinating the query */
  public ApiHostRef getCoordinator() {
    return coordinator;
  }
  
  public void setCoordinator(ApiHostRef coordinator) {
    this.coordinator = coordinator;
  }

  /** 
   * Whether we have a detailed runtime profile available for the query.
   * This profile is available at the endpoint /queries/{QUERY_ID}.
   * */
  public boolean getDetailsAvailable() {
    return detailsAvailable;
  }
  
  public void setDetailsAvailable(boolean detailsAvailable) {
    this.detailsAvailable = detailsAvailable;
  }

  /** The database on which this query was issued. */
  public String getDatabase() {
    return database;
  }
  
  public void setDatabase(String database) {
    this.database = database;
  }
  
  /** 
   * The duration of the query in milliseconds. If the query hasn't completed
   * then this will return null.
   */
  public Long getDurationMillis() {
    return durationMillis;
  }
  
  public void setDurationMillis(long durationMillis) {
    this.durationMillis = durationMillis;
  }

  @Override
  public String toString() {
    return Objects.toStringHelper(this)
                  .add("queryId", queryId)
                  .add("statement", statement)
                  .add("queryType", queryType)
                  .add("queryState", queryState)
                  .add("startTime", startTime)
                  .add("endTime", endTime)
                  .add("rowsProduced", rowsProduced)
                  .add("attributes", attributes)
                  .add("user", user)
                  .add("coordinator", coordinator)
                  .add("detailsAvailable", detailsAvailable)
                  .add("database", database)
                  .add("durationMillis", durationMillis)
                  .toString();
  }
}
